package cn.huolabao.service.impl;

import cn.huolabao.common.core.exception.LCException;
import cn.huolabao.common.core.utils.R;
import cn.huolabao.dao.SysUserMapper;
import cn.huolabao.dto.JwtTokenDto;
import cn.huolabao.dto.UserDetailDto;
import cn.huolabao.feign.OAuth2Client;
import cn.huolabao.model.SysPermission;
import cn.huolabao.model.SysRole;
import cn.huolabao.model.SysUser;
import cn.huolabao.model.SysUserRole;
import cn.huolabao.service.SysPermissionService;
import cn.huolabao.service.SysRoleService;
import cn.huolabao.service.SysUserRoleService;
import cn.huolabao.service.SysUserService;
import cn.huolabao.vo.portal.*;
import cn.huolabao.vo.system.UserVo;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.enums.ApiErrorCode;
import com.baomidou.mybatisplus.extension.exceptions.ApiException;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
@Slf4j
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {

    private final SysRoleService roleService;

    private final SysUserRoleService userRoleService;

    private final SysPermissionService permissionService;

    private final RedisTemplate<String, Object> redisTemplate;


    private final OAuth2Client oAuth2Client;

    /**
     * 给验证服务器获取用户权限信息等
     *
     * @param sysUser 用户实体
     * @return 用户实体信息
     */
    @Override
    public UserDetailDto getUserInfo(SysUser sysUser) {
        List<SysRole> sysRoles = roleService.selectRolesByUserId(sysUser.getId());
        List<Integer> roleIds = sysRoles.stream().map(SysRole::getId).collect(Collectors.toList());
        UserDetailDto userDetailDto = new UserDetailDto();
        BeanUtils.copyProperties(sysUser, userDetailDto);
        List<SysPermission> permissions = permissionService.selectPermsByRoleIds(roleIds);
        List<String> perms = new ArrayList<>();
        permissions.forEach(sysPermission -> {
            if (sysPermission.getPermissionType() == 2) {
                perms.add(sysPermission.getPermission());
            }
        });
        userDetailDto.setPerms(perms);
        return userDetailDto;
    }

    /**
     * 用户登陆
     *
     * @param username 用户名
     * @param password 密码
     * @return 登陆结果token
     */
    @Override
    public R login(String username, String password) {
        ResponseEntity<JwtTokenDto> tokenResponseEntity = oAuth2Client.getToken("password", username, password, "leechee-cloud", "123456");
        JwtTokenDto jwtTokenDto = tokenResponseEntity.getBody();
        if (ObjectUtils.isEmpty(jwtTokenDto.getAccessToken())) {
            String msg = jwtTokenDto.getMsg();
            return R.error(msg);
        }
        SysUser sysUser = selectUserByUserName(username);
        String accessToken = jwtTokenDto.getAccessToken();
        redisTemplate.opsForValue().set(accessToken, sysUser, jwtTokenDto.getExpiresIn(), TimeUnit.SECONDS);
        return R.ok(jwtTokenDto);
    }

    /**
     * 根据ant design pro要求格式返回用户路由信息
     *
     * @param username 用户名
     * @return 用户详情对象
     */
    @Override
    public UserPortalInfoVo getUserPortalInfo(String username) {
        SysUser sysUser = this.selectUserByUserName(username);
        List<SysRole> sysRoles = roleService.selectRolesByUserId(sysUser.getId());
        //每个用户都有至少一个角色
        SysRole sysRole = sysRoles.get(0);
        List<Integer> roleIds = sysRoles.stream().map(SysRole::getId).collect(Collectors.toList());
        List<SysPermission> permissions = permissionService.selectPermsByRoleIds(roleIds);
        List<PermissionVo> permissionVos = new ArrayList<>();
        permissions.forEach(sysPermission -> {
            if (sysPermission.getPermissionType() != 1) {
                return;
            }
            PermissionVo permissionVo = new PermissionVo();
            permissionVo.setPermissionId(sysPermission.getPermission());
            permissionVo.setPermissionName(sysPermission.getPermissionName());
            List<ActionEntitySetVo> actionEntitySet = new ArrayList<>();
            permissions.forEach(btnPerms -> {
                if (btnPerms.getPermissionType() == 2) {
                    if (btnPerms.getPid().equals(sysPermission.getId())) {
                        ActionEntitySetVo actionEntitySetVo = new ActionEntitySetVo();
                        actionEntitySetVo.setAction(btnPerms.getPermission());
                        actionEntitySetVo.setDescribe(btnPerms.getDescript());
                        actionEntitySet.add(actionEntitySetVo);
                    }
                }
            });
            permissionVo.setActionEntitySet(actionEntitySet);
            permissionVos.add(permissionVo);
        });
        RoleVo roleVo = new RoleVo();
        roleVo.setId(sysRole.getRoleCode());
        roleVo.setName(sysRole.getRoleName());
        roleVo.setDescribe(sysRole.getDescript());
        roleVo.setStatus(sysRole.getStatus());
        roleVo.setCreatorId(sysRole.getCreateBy());
        roleVo.setCreateTime(sysRole.getCreateTime());
        roleVo.setDeleted(sysRole.getIsDelete());
        roleVo.setPermissions(permissionVos);
        UserPortalInfoVo userPortalInfo = new UserPortalInfoVo();
        userPortalInfo.setId(sysUser.getId());
        userPortalInfo.setName(sysUser.getUsername());
        userPortalInfo.setUsername(sysUser.getUsername());
        userPortalInfo.setStatus(sysUser.getStatus());
        userPortalInfo.setTelephone(sysUser.getPhone());
        userPortalInfo.setCreteTime(sysUser.getCreateTime());
        userPortalInfo.setDeleted(sysUser.getIsDelete());
        userPortalInfo.setRoleId(sysRole.getRoleCode());
        userPortalInfo.setRole(roleVo);
        userPortalInfo.setRole(roleVo);
        return userPortalInfo;
    }

    /**
     * 根据用户名查询用户实体
     *
     * @param username 用户名
     * @return 用户实体
     */
    @Override
    public SysUser selectUserByUserName(String username) {
        return this.baseMapper.selectOne(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getUsername, username));
    }

    /**
     * 根据用户名获取用户菜单
     *
     * @param username 用户名
     * @return 菜单list集合
     */
    @Override
    public List<UserNavVo> getUserPortalNav(String username) {
        List<UserNavVo> userNavs = new ArrayList<>();
        SysUser user = this.getOne(Wrappers.<SysUser>query().lambda().eq(SysUser::getUsername, username));
        List<SysRole> sysRoles = roleService.selectRolesByUserId(user.getId());
        List<Integer> roleIds = sysRoles.stream().map(SysRole::getId).collect(Collectors.toList());
        List<SysPermission> permissions = permissionService.selectPermsByRoleIds(roleIds);
        permissions.forEach(permission -> {
            if (permission.getPermissionType() == 1) {
                UserNavVo userNav = new UserNavVo();
                userNav.setId(permission.getId());
                userNav.setName(permission.getComponentName());
                userNav.setComponent(permission.getComponent());
                userNav.setParentId(permission.getPid());
                userNav.setRedirect(permission.getRedirect());
                userNav.setPath(permission.getPath());
                MetaVo meta = new MetaVo();
                meta.setIcon(permission.getIcon());
                meta.setShow(true);
                meta.setLink(permission.getLink());
                meta.setTitle(permission.getPermissionName());
                userNav.setMeta(meta);
                userNavs.add(userNav);
            }
        });
        return userNavs;
    }

    /**
     * 根据条件获取用户列表
     *
     * @param sysUserPage 分页信息
     * @param sysUser     用户实体
     * @return 结果集
     */
    @Override
    public Page<SysUser> selectUserList(Page<SysUser> sysUserPage, SysUser sysUser) {
        return this.baseMapper.selectUserList(sysUserPage, sysUser);
    }

    /**
     * 添加用户
     *
     * @param userVo 用户实体
     * @return 添加结果
     */
    @Override
    @Transactional
    public boolean addUser(UserVo userVo) {
        SysUser sysUser = new UserVo();
        BeanUtils.copyProperties(userVo, sysUser);
        String password = sysUser.getPassword();
        //加密用户密码
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        String encodePassword = passwordEncoder.encode(password);
        sysUser.setPassword(encodePassword);
        boolean result = super.save(sysUser);
        if (result) {
            //添加角色
            int roleId = userVo.getRoleId();
            SysUserRole userRole = new SysUserRole();
            userRole.setRoleId(roleId);
            userRole.setUserId(sysUser.getId());
            userRoleService.save(userRole);
        }
        return result;
    }

}
